#pragma once

#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <string>
#include <clocale>
#include <algorithm>
#include <vector>

using namespace std;

template <class T>
class interval
{

private:
	T lower;
	T upper;


public:

	interval(){
		lower = upper = 0;
	}

	interval(T mean, double percent){
		lower = (T)(mean - mean * percent / 100.0);
		upper = (T)(mean + mean * percent / 100.0);
	}

	void setLower(T lower){
		this->lower = lower;
	}

	void setUpper(T upper){
		this->upper = upper;
	}

	~interval(){}

	T mean()
	{
		return (lower + upper) / 2;
	}

	double relative_error()
	{
		return (upper - lower) / 2 / mean();
	}

	double absolute_error()
	{
		return (upper - lower) / 2;
	}

	friend interval<T> operator + (const interval<T> &lop, const interval<T> &rop){
		interval<T> m;
		m.upper = lop.upper + rop.upper;
		m.lower = lop.lower + rop.lower;
		return m;
	}

	friend interval<T> operator - (const interval<T> &lop, const interval<T> &rop){
		interval<T> m;
		m.upper = lop.upper - rop.lower;
		m.lower = lop.lower - rop.upper;
		return m;
	}

	friend interval<T> operator * (const interval<T> &lop, const interval<T> &rop){
		interval<T> m;
		m.upper = max(max(max(lop.lower*rop.lower, lop.lower*rop.upper), lop.upper*rop.lower), lop.upper*rop.upper);
		m.lower = min(min(min(lop.lower*rop.lower, lop.lower*rop.upper), lop.upper*rop.lower), lop.upper*rop.upper);
		return m;
	}

	friend interval<T> operator / (const interval<T> &lop, const interval<T> &rop){
		interval<T> tmp;
		interval<T> m;
		tmp.lower = 1 / rop.upper;
		tmp.upper = 1 / rop.lower;
		m = lop * tmp;
		return m;
	}

	friend ostream& operator << (ostream &out, const interval<T> &rop)
	{
		out << "[" << rop.lower << "," << rop.upper << "]";
		return out;
	}


};

